﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Compilation;
using System.CodeDom;
using System.Web.UI;
using System.Text;
using System.Globalization;
using ExpressionBuilders.Design;

namespace ExpressionBuilders
{
    [ExpressionPrefix("Concat")]
    [ExpressionEditor(typeof(ConcatExpressionEditor))]
    public sealed class ConcatExpressionBuilder : ExpressionBuilder
    {
        #region Public static methods
        /// <summary>
        /// Parses the expression supplied in the ASPX or ASCX file into its components, and concatenates them according to their type.
        /// </summary>
        /// <param name="values">The exact expression supplied on the ASPX or ASCX file</param>
        /// <returns>A concatenated string</returns>
        public static String Concat(String values)
        {
            StringBuilder builder = new StringBuilder();
            String[] parts = values.Split(',');

            foreach (String part in parts)
            {
                String p = part.Trim();

                if (p.StartsWith("\'", StringComparison.OrdinalIgnoreCase) == true)
                {
                    Int32 i = p.IndexOf('\'', 1);

                    builder.Append(p.Substring(1, i - 1));
                }
                else
                {
                    if (p.Contains('.') == true)
                    {
                        String[] resourceParts = p.Split('.');
                        String classKey = resourceParts[0];
                        String resourceKey = resourceParts[1];

                        builder.Append(HttpContext.GetGlobalResourceObject(classKey, resourceKey, CultureInfo.CurrentUICulture));
                    }
                    else
                    {
                        String resourceKey = p;

                        builder.Append(HttpContext.GetLocalResourceObject(HttpContext.Current.Request.Path, resourceKey, CultureInfo.CurrentUICulture));
                    }
                }
            }

            //return (HttpUtility.HtmlEncode(builder.ToString()));
            return (builder.ToString());
        }
        #endregion
       
        #region Public override methods

        /// <summary>
        /// When overridden in a derived class, returns an object that represents an evaluated expression.
        /// </summary>
        /// <param name="target">The object containing the expression.</param>
        /// <param name="entry">The object that represents information about the property bound to by the expression.</param>
        /// <param name="parsedData">The object containing parsed data as returned by <see cref="M:System.Web.Compilation.ExpressionBuilder.ParseExpression(System.String,System.Type,System.Web.Compilation.ExpressionBuilderContext)"/>.</param>
        /// <param name="context">Contextual information for the evaluation of the expression.</param>
        /// <returns>
        /// An object that represents the evaluated expression; otherwise, null if the inheritor does not implement <see cref="M:System.Web.Compilation.ExpressionBuilder.EvaluateExpression(System.Object,System.Web.UI.BoundPropertyEntry,System.Object,System.Web.Compilation.ExpressionBuilderContext)"/>.
        /// </returns>
        public override Object EvaluateExpression(Object target, BoundPropertyEntry entry, Object parsedData, ExpressionBuilderContext context)
        {
            return (Concat(entry.Expression));
        }

        /// <summary>
        /// When overridden in a derived class, returns code that is used during page execution to obtain the evaluated expression.
        /// </summary>
        /// <param name="entry">The object that represents information about the property bound to by the expression.</param>
        /// <param name="parsedData">The object containing parsed data as returned by <see cref="M:System.Web.Compilation.ExpressionBuilder.ParseExpression(System.String,System.Type,System.Web.Compilation.ExpressionBuilderContext)"/>.</param>
        /// <param name="context">Contextual information for the evaluation of the expression.</param>
        /// <returns>
        /// A <see cref="T:System.CodeDom.CodeExpression"/> that is used for property assignment.
        /// </returns>
        public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, Object parsedData, ExpressionBuilderContext context)
        {
            if (String.IsNullOrEmpty(entry.Expression) == true)
            {
                return (new CodePrimitiveExpression(String.Empty));
            }
            else
            {
                return (new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(this.GetType()), "Concat"), new CodePrimitiveExpression(entry.Expression)));
            }
        }
        #endregion

        #region Public override properties

        /// <summary>
        /// When overridden in a derived class, returns a value indicating whether the current <see cref="T:System.Web.Compilation.ExpressionBuilder"/> object supports no-compile pages.
        /// </summary>
        /// <value></value>
        /// <returns>true if the <see cref="T:System.Web.Compilation.ExpressionBuilder"/> supports expression evaluation; otherwise, false.
        /// </returns>
        public override Boolean SupportsEvaluate
        {
            get
            {
                return (true);
            }
        }
        #endregion        
    }
}
